package com.speedata.blereaderdemo

import android.app.Application
import android.bluetooth.BluetoothDevice
import android.util.Log
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import com.hc.device.BleScanCallback
import com.hc.device.Reader
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.IOException
import java.util.concurrent.atomic.AtomicBoolean
import android.graphics.Bitmap
class BleReaderManager(application: Application) : AndroidViewModel(application) {

    // 设备扫描结果
    private val _scanResults = MutableLiveData<List<BluetoothDevice>>()
    val scanResults: LiveData<List<BluetoothDevice>> = _scanResults
    // 连接状态
    private val _isConnected = MutableLiveData<Boolean>()
    val isConnected: LiveData<Boolean> = _isConnected
    // 读卡器实例
    private val reader: Reader
    // 设备列表
    private val deviceList = mutableListOf<BluetoothDevice>()
    // 电量 LiveData
    private val _batteryLevel = MutableLiveData<Short>()
    val batteryLevel: LiveData<Short> = _batteryLevel
    private var batteryJob: Job? = null
    var connectedDeviceAddress: String? = null
    // 卡片SN结果，Pair<成功/失败, SN字符串或null>
    private val _cardSnResult = MutableLiveData<Pair<Boolean, String?>>()
    val cardSnResult: LiveData<Pair<Boolean, String?>> = _cardSnResult
    // 收发指令结果，Pair<成功/失败, 响应数据>
    private val _transmitResult = MutableLiveData<Pair<Boolean, String?>>()
    val transmitResult: LiveData<Pair<Boolean, String?>> = _transmitResult
    //解锁返回
    private val  _unlockResult = MutableLiveData<Pair<Boolean, String?>>()
    val unlockResult : LiveData<Pair<Boolean, String?>> = _unlockResult

    private val  _screenResult = MutableLiveData<Pair<Boolean, String?>>()
    val screenResult : LiveData<Pair<Boolean, String?>> = _screenResult
    // 防抖机制
    private var scanUpdateJob: Job? = null
    private val isScanning = AtomicBoolean(false)

    init {
        // 初始化 Reader，传入回调
        reader = Reader(application, object : BleScanCallback {
            override fun onReceiveScanDevice(device: BluetoothDevice, rssi: Int, scanRecord: ByteArray) {
                // 名称过滤
                if (filterName != null && (device.name == null || !device.name.contains(filterName!!))) {
                    return
                }
                if (deviceList.none { it.address == device.address }) {
                    deviceList.add(device)
//                    _scanResults.postValue(deviceList.toList())
                    debounceScanUpdate()
                }
            }
            override fun onScanDeviceStopped() {
                // 可处理扫描停止事件
                _scanResults.postValue(deviceList.toList())
                isScanning.set(false)
            }
        })
    }

    /** 开始扫描 */
    fun startScan(scanTimeMillis: Long = 5000, filterName: String? = "BLE NFC Reader") {
        if (!reader.isSupportsBLE()) {
            // 通知 UI 层不支持 BLE
            _scanResults.postValue(emptyList())
            return
        }
        deviceList.clear()
        _scanResults.postValue(deviceList)
        this.filterName = filterName
        isScanning.set(true)
        reader.startScan(scanTimeMillis)
    }

    // 新增：用于过滤名称
    private var filterName: String? = null

    // 防抖更新扫描结果
    private fun debounceScanUpdate() {
        scanUpdateJob?.cancel()
        scanUpdateJob = viewModelScope.launch {
            delay(300) // 300ms防抖延迟
            if (isScanning.get()) {
                _scanResults.postValue(deviceList.toList())
            }
        }
    }

    /** 停止扫描 */
    fun stopScan() {
        reader.stopScan()
        isScanning.set(false)
        scanUpdateJob?.cancel()
    }

    /** 连接设备 */
    fun connect(device: BluetoothDevice, onResult: (Boolean) -> Unit) {
        stopScan()
        // 如果已连接同一个设备，直接回调成功
        if (connectedDeviceAddress == device.address && _isConnected.value == true) {
            onResult(true)
            return
        }
        viewModelScope.launch {
            try {
                // 在IO线程执行连接操作
                val result = withContext(Dispatchers.IO) {
                    reader.OpenReader(device)
                }
                val success = result == 0.toShort()
                if (success) {
                    connectedDeviceAddress = device.address
                }
                _isConnected.postValue(success)

                // 在主线程执行回调
                withContext(Dispatchers.Main) {
                    onResult(success)
                }
            } catch (e: Exception) {
                _isConnected.postValue(false)
                withContext(Dispatchers.Main) {
                    onResult(false)
                }
            }
        }
    }

    /** 断开连接 */
    fun disconnect() {
        viewModelScope.launch(Dispatchers.IO) {
            reader.disconnectReader()
            _isConnected.postValue(false)
            connectedDeviceAddress = null
        }
    }

    /** 读设备名 */
    fun getDeviceName(): String? {
        return try {
            reader.dv_get_name()
        } catch (e: Exception) {
            null
        }
    }

    /** 调用rf_scard，返回卡片SN或失败 */
    fun scanCard() {
        viewModelScope.launch {
            try {
                val result = scanCardSync()
                _cardSnResult.postValue(result)
            } catch (e: Exception) {
                _cardSnResult.postValue(Pair(false, null))
            }
        }
    }



    /** 封装rf_transmit14443用于收发指令 */
    fun transmit14443(cmd: ByteArray) {
        viewModelScope.launch {
            try {
                val result = transmit14443Sync(cmd)
                _transmitResult.postValue(result)
            } catch (e: Exception) {
                _transmitResult.postValue(Pair(false, null))
            }
        }
    }

    /** 同步版本的transmit14443 */
    suspend fun transmit14443Sync(cmd: ByteArray): Pair<Boolean, String?> {
        return withContext(Dispatchers.IO) {
            try {
                val resp = ByteArray(256)
                val crcMode: Byte = 0x11
                val result = reader.rf_transmit14443(crcMode, cmd, cmd.size.toShort(), resp)
                Log.e("Transmit14443", "返回: ${result}")
                if (result >= 0) {
                    val data = resp.copyOf(result.toInt())
                    Pair(true, data.toHexString())
                } else {
                    Pair(false, result.toString())
                }
            } catch (e: Exception) {
                Log.e("Transmit14443", "发送命令异常: ${e.message}")
                Pair(false, null)
            }
        }
    }

    /** 开始定时获取电量 */
    fun startBatteryPolling(intervalMillis: Long = 10000) {
        batteryJob?.cancel()
        batteryJob = viewModelScope.launch {
            while (true) {
                try {
                    val soc = withContext(Dispatchers.IO) {
                        reader.GetBleReaderSOC()
                    }
                    _batteryLevel.postValue(soc)
                } catch (e: Exception) {
                    // 电量读取失败时不更新UI
                }
                delay(intervalMillis)
            }
        }
    }

    /** 停止定时获取电量 */
    fun stopBatteryPolling() {
        batteryJob?.cancel()
        batteryJob = null
    }

    /** 解锁函数 */
    suspend fun newLockUnlock() {
        try {
            val unlock = transmit14443Sync(ReaderCommands.NEW_LOCK_UNLOCK)
            if (!unlock.first) {
                _unlockResult.postValue(Pair(false,"AD10失败${unlock.second}"))
                return
            }
            delay(300)
            val unlock2 = transmit14443Sync(ReaderCommands.NEW_LOCK_UNLOCK2)
            if (!unlock2.first) {
                _unlockResult.postValue(Pair(false,"AD10失败"))
                return
            }
            _unlockResult.postValue(Pair(true, "UnlockSuccess"))
        } catch (e: Exception) {
            Log.e("BleReader", "解锁异常: ${e.message}")
            _unlockResult.postValue(Pair(false,e.message))
            throw IOException("解锁发送中断", e)
        }
    }

    /** 刷屏函数（优化版本） */
    suspend fun newLockBigScreen(screenPhotoData: ByteArray) {
        try {
            Log.d("BleReader", "开始刷屏，数据长度: ${screenPhotoData.size}")

            // 发送初始化命令
            val initScreen = transmit14443Sync(ReaderCommands.NEW_LOCK_SCREEN_INIT)
            Log.d("BleReader", "newLockInitScreen: $initScreen")
            if (!initScreen.first) {
                _screenResult.postValue(Pair(false,"AD40失败${initScreen.second}"))
                return
            }

            // 分块发送数据
            val chunkSize = 240
            val totalChunks = (screenPhotoData.size + chunkSize - 1) / chunkSize
            Log.d("BleReader", "总块数: $totalChunks, 每块大小: $chunkSize")

            for (chunkIndex in 0 until totalChunks) {
                val startIndex = chunkIndex * chunkSize
                val endIndex = minOf(startIndex + chunkSize, screenPhotoData.size)
                val chunkData = screenPhotoData.copyOfRange(startIndex, endIndex)

                Log.d("BleReader", "发送块 $chunkIndex: 数据长度=${chunkData.size}")

                val cmd = Utils.byteMerger(
                    ReaderCommands.NEW_LOCK_SCREEN_DATA,
                    Utils.intToTwoBytes(chunkIndex),
                    chunkData
                )

                val response = transmit14443Sync(cmd)
                // 检查每个块的响应
                if (!response.first) {
                    _screenResult.postValue(Pair(false,"AD20失败${response.second}"))
                    return
                }


                // 在每个块之间添加小延迟
                delay(50)
            }

            Log.d("BleReader", "所有数据块发送完成，开始刷屏")

            // 发送刷屏命令
            val flashRet = transmit14443Sync(ReaderCommands.NEW_LOCK_FLASH)

            if (!flashRet.first) {
                _screenResult.postValue(Pair(false,"AD42失败${flashRet.second}"))
                return
            }

            // 等待3秒
            Log.d("BleReader", "等待3秒...")
            delay(3000)

            // 发送锁定命令
            val lockRest = transmit14443Sync(ReaderCommands.NEW_LOCK_LOCK)
            Log.d("BleReader", "刷屏完成")
            _screenResult.postValue(Pair(true,"刷屏完成"))
        } catch (e: Exception) {
            Log.e("BleReader", "刷屏异常: ${e.message}")
//            _screenResult.postValue(Pair(false,"刷屏异常: ${e.message}"))
            throw IOException("刷屏发送中断", e)
        }
    }


    fun ByteArray.toHexString(): String {
        return this.joinToString("") { byte -> "%02X".format(byte) }
    }
    fun startUnlock() {
        viewModelScope.launch {
            try {
                newLockUnlock()
            } catch (e: Exception) {
                Log.e("BleReader", "解锁失败: ${e.message}")
            }
        }
    }

    /** 公共刷屏方法，供ViewModel调用 */
    fun startScreenUpdate(bitmap: Bitmap) {
        viewModelScope.launch {
            try {
                val screenData = Utils.getBlackWhiteByte(bitmap)
                newLockBigScreen(screenData)
            } catch (e: Exception) {
                Log.e("BleReader", "刷屏失败: ${e.message}")
            }
        }
    }

    /** 测试刷屏方法，使用白色屏幕数据 */
//    fun testScreenUpdate() {
//        viewModelScope.launch {
//            try {
//                Log.d("BleReader", "开始测试刷屏")
//                newLockBigScreen(Utils.whiteScreen)
//                Log.d("BleReader", "测试刷屏成功")
//            } catch (e: Exception) {
//                Log.e("BleReader", "测试刷屏失败: ${e.message}")
//            }
//        }
//    }

    /** 同步读卡方法，供需要立即结果的地方使用 */
    suspend fun scanCardSync(): Pair<Boolean, String?> {
        return withContext(Dispatchers.IO) {
            try {
                // 先激活读卡器
                reader.rf_reset(10)
                // 等待200ms
                delay(200)
                
                val snr = ByteArray(16)
                val result = reader.rf_scard(1, snr)
                Log.e("ScanCard", result.toString())
                
                if (result >= 0) {
                    // 取有效长度的SN
                    val sn = snr.copyOf(result.toInt()).joinToString(separator = "") { String.format("%02X", it) }
                    reader.dv_beep(10)
                    Pair(true, sn)
                } else {
                    Pair(false, null)
                }
            } catch (e: Exception) {
                Log.e("ScanCard", "读卡异常: ${e.message}")
                Pair(false, null)
            }
        }
    }


    override fun onCleared() {
        super.onCleared()
        stopBatteryPolling()
        scanUpdateJob?.cancel()
    }

    /** 其他 Reader 方法可继续封装... */

}
